import re
from enum import Enum
from typing import Optional, List, Union

from flask import g
from pydantic import BaseModel, Field, validator
from sqlalchemy import select, or_

from apps.user import user_const

from config.const import error_code, constant
from database.db_manager import db_session
from database.user_model import users, DBCustomQuery, roles as model_roles
from forword.custom_error.request_errors import RequestError
from utils.encrypt_helper import encrypt_util
from utils.everying import tailor_monster

PHONE_REGEX = '^[1]\d{10}$'

def validate_phone(phone):
    if phone is None:
        return False

    return re.search(PHONE_REGEX, phone)

def verify_phone(phone):
    if phone is None:
        return None

    if not validate_phone(phone):
        return None

    return phone

def check_password_length(cls, password):
    if not (user_const.MIN_PASSWORD_LENGTH <= len(password) <= user_const.MAX_PASSWORD_LENGTH):
        raise RequestError(f"密码长度为{user_const.MIN_PASSWORD_LENGTH}到{user_const.MAX_PASSWORD_LENGTH}之间")
    return password.strip()

class PasswordLoginForm(BaseModel):
    password: str = Field(..., title="密码")
    username: str = Field(..., title="用户名/手机号")

    @validator('password')
    def check_password_length(cls, password):
        return check_password_length(cls, password)

    @validator('username')
    def check_user(cls, username, values):
        from config import server_config

        if not (user_const.MIN_USERNAME_LENGTH <= len(username) <= user_const.MAX_USERNAME_LENGTH):
            raise RequestError(f"用户名长度为{user_const.MIN_USERNAME_LENGTH}到{user_const.MAX_USERNAME_LENGTH}之间")

        # if server_config.restrict_tool.check(username, user_const.PWD_LOGIN_MAXIMUM_VALUE_OF_THE_LIMIT):
        #     raise RequestError("密码错误次数超出限制,请稍后再试")

        user = DBCustomQuery(users).where(or_(users.c.username == username, users.c.mobile == username)).fetchone()

        if not user:
            raise RequestError("用户不存在")
        # user = get_model_value_one({"name": username}, UserModel)

        #
        if not encrypt_util.verify(values.get("password"), user.password):
            # server_config.restrict_tool.add(username, user_const.PWD_LOGIN_TIMEOUT)
            raise RequestError(error_code.CODE_USER_PASSWORD_FAIL)
        #
        # server_config.restrict_tool.delete(username)
        user_info = dict(user)
        del user_info["password"]
        user_info = tailor_monster.format_datetime(user_info)
        user_info["roles"] = user_info["roles"].split(",")
        values["user_info"] = user_info
        return username.strip()

class RegisterBaseForm(BaseModel):
    password: str = Field(..., title="密码")
    mobile: str = Field(..., title="手机号")
    username: str = Field(..., title="用户名")
    roles: list = Field(default=[], title="角色")

    @validator('password')
    def check_password_length(cls, password):
        return check_password_length(cls, password)

    @validator('mobile')
    def phone_match(cls, mobile):

        if mobile and verify_phone(mobile) is None:
            raise RequestError("手机号格式错误")

        if DBCustomQuery(users, ["password"]).where(users.c.mobile == mobile).fetchall():
            raise RequestError("手机号重复")
        return mobile.strip()

    @validator('username')
    def check_user(cls, username, values):
        from config import server_config

        if not (user_const.MIN_USERNAME_LENGTH <= len(username) <= user_const.MAX_USERNAME_LENGTH):
            raise RequestError(f"用户名长度为{user_const.MIN_USERNAME_LENGTH}到{user_const.MAX_USERNAME_LENGTH}之间")

        if DBCustomQuery(users, ["password"]).where(users.c.username == username).fetchone():
            raise RequestError("用户名已存在")

        return username.strip()

    @validator('roles')
    def check_roles(cls, roles):
        if roles is None:
            return roles
        db_roles = list(map(lambda x: dict(x).pop("role"), DBCustomQuery(model_roles).fetchall()))
        if len(set(roles) & set(db_roles)) == 0:
            raise RequestError("角色不存在")
        return roles

    # @validator('key')
    # def check_key(cls, key):
    #     if key != constant.INTERNAL_KEY:
    #         raise RequestError("key错误")
    #     return key


class SearchUserForm(BaseModel):
    search: str = Field(default=None, title="过滤条件")
    page_num: int = Field(default=1, alias="pageNum", title="页数")
    page_size: int = Field(default=10, alias="pageSize", title="页面数量大小")

    @validator('search')
    def check_search(cls, search):
        return search.strip()


class SearchRoleForm(BaseModel):
    search: str = Field(default=None, title="过滤条件")
    page_num: int = Field(default=1, alias="pageNum", title="页数")
    page_size: int = Field(default=10, alias="pageSize", title="页面数量大小")

    @validator('search')
    def check_search(cls, search):
        return search.strip()


class UpdateUserForm(BaseModel):
    id: int = Field(..., title="id")
    mobile: str = Field(default=None, title="手机号")
    password: str = Field(default=None, title="密码")
    roles: list = Field(default=[], title="角色")
    username: str = Field(default=None, title="用户名")

    @validator('mobile')
    def phone_match(cls, mobile):
        if mobile is None:
            return mobile
        if mobile and verify_phone(mobile) is None:
            raise RequestError("手机号格式错误")

        # if DBCustomQuery(users, ["password"]).where(users.c.mobile == mobile).fetchall():
        #     raise RequestError("手机号重复")
        return mobile.strip()

    @validator('password')
    def check_password_length(cls, password):
        if password is None:
            return password
        return check_password_length(cls, password)

    @validator('roles')
    def check_roles(cls, roles):
        if roles is None:
            return roles
        db_roles = list(map(lambda x: dict(x).pop("role"), DBCustomQuery(model_roles).fetchall()))
        if len(set(roles) & set(db_roles)) == 0:
            raise RequestError("角色不存在")
        return roles

    @validator('username')
    def check_user(cls, username, values):
        if username is None:
            return username
        if not (user_const.MIN_USERNAME_LENGTH <= len(username) <= user_const.MAX_USERNAME_LENGTH):
            raise RequestError(f"用户名长度为{user_const.MIN_USERNAME_LENGTH}到{user_const.MAX_USERNAME_LENGTH}之间")

        # if DBCustomQuery(users, ["password"]).where(users.c.username == username).fetchone():
        #     raise RequestError("用户名已存在")

        return username.strip()